package uk.ac.lkl.lpp;



import java.awt.BorderLayout;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.IllegalArgumentException; 
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.logging.FileHandler;

import javax.swing.*;

import uk.ac.lkl.common.ui.SimpleMsgDialog;
import uk.ac.lkl.common.util.Args;
import uk.ac.lkl.common.util.Resources;

import uk.ac.lkl.lpp.ui.PedagogyPlannerMenuBar;
import uk.ac.lkl.lpp.ui.Messages;
import uk.ac.lkl.lpp.xml.XMLException;


public class LondonPedagogyPlanner extends JFrame {
	private static final long serialVersionUID = 1L;
	
	private static final Logger logger = Logger.getLogger("uk.ac.lkl.lpp");

	private static final String PARAM_LOG_FILE = "lf";
	private static final String PARAM_GENERATE_MESSAGES = "gm";
	private static final String PARAM_READ_MESSAGES = "mf";	
	private static final String PARAM_HELP = "help";		
	private static final String[] CMD_LINE_PARAMS = {PARAM_GENERATE_MESSAGES,PARAM_READ_MESSAGES,PARAM_HELP,PARAM_LOG_FILE};
	private static final String SYNOPSIS = "LondonPedagogyPlanner -gm [out messages file] -mf [in messages file] \n"+
										   "-gm: generate messages\n"+
										   "-mf: read messages";
	
	public static final String HELP_ABOUT_LOCATION    = "resources/data/about.html";
	public static final String HELP_CONTENTS_LOCATION = "resources/data/help.html";
	public static final String RELEASE_NOTES_LOCATION = "resources/data/release-notes.html";
	
	private static Args clargs = null;

    private PedagogyPlan plan;
    
    /*
     * show this on help / about
     */
    private SimpleMsgDialog aboutDialog; 
    
    /**
     * help / contents
     */
    private SimpleMsgDialog helpDialog;
    
    /**
     * release notes
     */
    private SimpleMsgDialog relNotesDialog;
    
    /**
     * dialog for opening / saving files
     */
    private JFileChooser fileChooser;
    
    /**
     * current working file
     */
    File currentFile;

    /**
     * needs saving?
     */
    private boolean dirty = true;
    
    public static ClassLoader classloader = LondonPedagogyPlanner.class.getClassLoader();


    public LondonPedagogyPlanner() {
        super("The London Pedagogy Planner");
        setJMenuBar(new PedagogyPlannerMenuBar(this,plan));    	
        createPlan();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
        
        String text = null;
        // configure help / about
        try {
        	text = Resources.getResourceString(HELP_ABOUT_LOCATION);
        }
        catch (Exception e) {
        	logger.severe("can't show help / about "+text+":" +e);
        	text = e.toString();
        }
        aboutDialog =  new SimpleMsgDialog(this,"London Pedagogy Planner: About",text);
        
        // configure help / contents
        try {
        	text = Resources.getResourceString(HELP_CONTENTS_LOCATION);
        }
        catch (Exception e) {
        	logger.severe("can't show help / contents "+text+":" +e);
        	text = e.toString();
        }
        helpDialog =  new SimpleMsgDialog(this,"London Pedagogy Planner: About",text);
        
        // configure release notes
        try {
        	text = Resources.getResourceString(RELEASE_NOTES_LOCATION);
        }
        catch (Exception e) {
        	logger.severe("can't show release notes "+text+":" +e);
        	text = e.toString();
        }
        relNotesDialog =  new SimpleMsgDialog(this,"London Pedagogy Planner: Release Notes",text);
        
        // config filechooser
        
        fileChooser = new JFileChooser(FileUtils.getCurrentDirectory());
        fileChooser.setMultiSelectionEnabled(false);
        fileChooser.setAcceptAllFileFilterUsed(false);
        fileChooser.setFileFilter(FileUtils.fileFilter);      
    }
    
    /**
     * create and display a new plan.
     *
     */
    public void createPlan() {
    	// should close exisiting plan nicely.
    	if (plan != null) {
    		getContentPane().remove(plan.getUI());    		
    	}
    	
        plan = new PedagogyPlan();
        dirtyListener.setPlan(plan);
        try {
            URL url = classloader.getResource("resources/data/default.lpp");
            URI uri = url.toURI();
            plan.readFromURI(uri);
        }
        catch (XMLException e) {
        	logger.log(Level.SEVERE, "create plan failed, bailing out.", e);
            System.exit(1);
        }
        catch (URISyntaxException e) {
        	logger.log(Level.SEVERE, "create plan failed, bailing out.", e);
            // todo: handle this much better
            System.exit(1);
        }

        getContentPane().add(plan.getUI(), BorderLayout.CENTER);
        pack();

    }
    
    /**
     * open a plan from file.
     *
     */
    public void openPlan(File f){
    	try {
    		plan.readFromFile(f);
    	} catch (XMLException e){
        	logger.log(Level.SEVERE, "open plan failed, bailing out.", e);
    	}
    }
    
    public void openPlan(){
    	if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
    		currentFile = fileChooser.getSelectedFile(); 
    		openPlan(currentFile);
    		FileUtils.setCurrentDirectory(fileChooser.getSelectedFile());
    	}
    }
    
    public void savePlan(File f){
        plan.writeToFile(f);
        dirty = false;
    }
    
    public void savePlan(){
    	if (currentFile == null) {
    		saveAsPlan();
    		return;
    	}
    	savePlan(currentFile);
    }
    
    public void saveAsPlan() {
    	if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
    		currentFile = fileChooser.getSelectedFile(); 
    		savePlan(currentFile);
    		FileUtils.setCurrentDirectory(fileChooser.getSelectedFile());
    	}
    }
    
    public boolean needsSave() {
    	return dirty;
    }
    
    public File getCurrentFile() {
    	return currentFile;
    }
    
    public void showAbout(){
    	aboutDialog.setVisible(true);
    }
    
    public void showHelp(){
    	helpDialog.setVisible(true);
    }
    
    public void showReleaseNotes(){
    	relNotesDialog.setVisible(true);
    }

    public void exit() {
        // todo: prompt for saving or save automatically
        System.exit(0);
    }

    public static final String getArg(String key) {
    	return clargs.get(key);
    }
    
    public static final void synopsis() {
    	System.out.println(SYNOPSIS);
    }

    public static final void help() {
    	System.out.println(SYNOPSIS);
    }
        
    /**
     * 
     * @param args
     */
    public static void main(String[] args) {
        try {
        	clargs = new Args(args,CMD_LINE_PARAMS);
        	
        	// print help and exit
        	if (clargs.containsKey(PARAM_HELP)) {
            	synopsis();
            	System.exit(0);
        	}
        	
        	// log to file
        	if (clargs.containsKey(PARAM_LOG_FILE)) {
        		String lFileName = clargs.get(PARAM_LOG_FILE);
        		System.out.println("saving log messages to "+lFileName);
            	try {
                    FileHandler handler = new FileHandler(lFileName);
                    logger.addHandler(handler);
                } catch (Exception e) {
                	System.out.println("failed to open log file");
                }
        	}
        	
        	// generate messages file
        	if (clargs.containsKey(PARAM_GENERATE_MESSAGES)) {
        		String outFileName = clargs.get(PARAM_GENERATE_MESSAGES);
        		if (outFileName == null || outFileName.length() == 0) {
        			System.out.println("writing messages to sys.out");
        			Messages.setOutputStream(System.out);
        		} else {
        			System.out.println("writing messages to "+outFileName);
        			Messages.setOutputStream(new FileOutputStream(outFileName));
        		}
        	}
        	
        	// read messages from file
        	if (clargs.containsKey(PARAM_READ_MESSAGES)) {
        		String mFileName = clargs.get(PARAM_READ_MESSAGES);
        		System.out.println("reading Messages from "+mFileName);
        		if (mFileName == null || mFileName.length() == 0) {
        			Messages.loadFromStream(System.in);
        		} else {
        			Messages.loadFromFile(mFileName);
        		}
        	
        	}
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        }
        catch (IllegalArgumentException e) {
        	synopsis();
        	System.exit(1);
        }
        catch (Exception e) {
            // do nothing
            e.printStackTrace();
        }

    	LondonPedagogyPlanner runner = new LondonPedagogyPlanner();
        
        runner.setVisible(true);
    }
}
